/**
 * @class MapService.Control.Slider
 * @extends OpenLayers.Control
 * Adiciona barra de navegação no mapa.
 * 
 * Exemplo de uso:
 * 
 *     mapService.map.addControl(new MapService.Control.Slider());
 *     
 */
MapService.Control.Slider = OpenLayers.Class(OpenLayers.Control, {
	panAmount       : 100,	
    element         : null,
    divSlider       : null,
    slider          : null,
    sliderEvents    : null,
    divEvents       : null,
    mouseDragStart  : null,
    zoomStart       : null,
    zoomStopHeight  : 4,
    
	/**
     * @cfg {Object}
     * Posição do Slider no mapa.
     * 
     * Exemplo de uso:
     * 
     * Alinhar no canto superior esquerdo:
     * 
	 *     mapService.map.addControl(new MapService.Control.Slider({
	 *     	position: {
	 *     		top   : 10,
	 *     		left  : 10
	 *     	}
	 *     }));
	 *     
	 *     
	 * Alinhar no canto superior direito:
	 *  
	 *     mapService.map.addControl(new MapService.Control.Slider({
	 *     	position: {
	 *     		top   : 10,
	 *     		right : 10
	 *     	}
	 *     }));
	 *     
     * 
     * @param {Number} left Alinhamento a partir da esquerda.
     * @param {Number} [right=10] Alinhamento a partir da direita.
     * @param {Number} [top=10] Alinhamento a partir do topo.
     * @param {Number} bottom Alinhamento a partir da base.
     */
    position        : {
        left            : null,
        right           : 10,
        top             : 10,
        bottom          : null
    },
    
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, [options]);
    },
    
    destroy: function() {
    	this._removeSlider();

        this.map.events.un({
            "changebaselayer": this.redraw,
            scope: this
        });

        OpenLayers.Control.prototype.destroy.apply(this, arguments);
        
        delete this.mouseDragStart;
        delete this.zoomStart;
    },
    
    setMap: function(map) {
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
        this.map.events.register("changebaselayer", this, this.redraw);
        
        if (OpenLayers.String.contains(navigator.appName, "Microsoft")) {
        	this.map.events.register("resize", this, this.redraw);
        } else {
            OpenLayers.Event.observe(window, 'resize', OpenLayers.Function.bind(this.redraw,this)); 
        };
    },

    redraw: function() {
        if (this.div != null) {
            this._removeSlider();
        };
        
        this.draw();
    },
    
    _removeSlider: function() {
    	this.sliderEvents.un({
			"mousedown": this.sliderMouseDown,
			"mousemove": this.sliderMouseDrag,
			"mouseup": this.sliderMouseUp,
			"dblclick": this.stopEvent,
			"click": this.stopEvent
		});
        this.sliderEvents.destroy();

		this.divEvents.un({
			"mousedown": this.stopEvent,
			"mousemove": this.passEventToSlider,
			"dblclick": this.stopEvent,
			"click": this.stopEvent
		});
        this.divEvents.destroy();
        
        if(this.element){
        	this.div.removeChild(this.element);
        	this.element = null;
        };
        
        this.divSlider = null;
        this.slider = null;
        
        this.map.events.unregister("zoomend", this, this.updateSliderPosition);
    },
    
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);
        if (!this.element) {
            this.element = document.createElement("div");
            this.div.appendChild(this.element);
        }
        this.element.unselectable = 'on';
        
        //this.calulateSliderPosition();
        
        this.map.events.register("zoomend", this, this.updateSliderPosition);
        
        this.divEvents = new OpenLayers.Events(this, this.div, null, true,{includeXY: true});
		this.divEvents.on({
			"mousedown": this.stopEvent,
			"mousemove": this.passEventToSlider,
			"dblclick": this.stopEvent,
			"click": this.stopEvent
		});
        
        OpenLayers.Event.observe(this.element, "dblclick", OpenLayers.Function.bindAsEventListener(this.stopEvent, this.element));
        OpenLayers.Event.observe(this.element, "click", OpenLayers.Function.bindAsEventListener(this.stopEvent, this.element));
        
        var m = document.createElement('map');
        m.name = 'Navigator_ImageMap';
        m.id = 'Navigator_ImageMap';

        var a = document.createElement('area');
        a.shape = 'poly';
        a.alt = OpenLayers.i18n('Mover p/ Leste');
        a.title = OpenLayers.i18n('Mover p/ Leste');
        a.coords = '27,176, 27,177, 40,190, 44,182, 44,159';
        var panEast = OpenLayers.Function.bind(this.pan, this, this.panAmount, 0);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(panEast, this));
        m.appendChild(a);

        var a = document.createElement('area');
        a.shape = 'poly';
        a.alt = OpenLayers.i18n('Mover p/ Oeste');
        a.title = OpenLayers.i18n('Mover p/ Oeste');
        a.coords = '24,177, 24,176, 7,159, 7,182, 11,190';
        var panWest = OpenLayers.Function.bind(this.pan, this, -this.panAmount, 0);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(panWest, this) );
        m.appendChild(a);

        var a = document.createElement('area');
        a.shape = 'poly';
        a.alt = OpenLayers.i18n('Mover p/ Sul');
        a.title = OpenLayers.i18n('Mover p/ Sul');
        a.coords = '25,178, 12,191, 21,197, 30,197, 39,191, 26,178';
        var panSouth = OpenLayers.Function.bind(this.pan, this, 0, this.panAmount);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(panSouth, this));
        m.appendChild(a);

        var a = document.createElement('area');
        a.shape = 'poly';
        a.alt = OpenLayers.i18n('Mover p/ Norte');
        a.title = OpenLayers.i18n('Mover p/ Norte');
        a.coords = '26,175, 43,158, 8,158, 25,175';
        var panNorth = OpenLayers.Function.bind(this.pan, this, 0, -this.panAmount);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(panNorth, this) );
        m.appendChild(a);

        var a = document.createElement('area');
        a.shape = 'circle';
        a.alt = OpenLayers.i18n('Afastar');
        a.title = OpenLayers.i18n('Afastar');
        a.coords = '25,142,8';
        var zoomOut = OpenLayers.Function.bind(this.zoomOut, this);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(zoomOut, this) );
        m.appendChild(a);

        var a = document.createElement('area');
        a.shape = 'circle';
        a.alt = OpenLayers.i18n('Aproximar');
        a.title = OpenLayers.i18n('Aproximar');
        a.coords = '25,34,8';
        var zoomIn = OpenLayers.Function.bind(this.zoomIn, this);
        OpenLayers.Event.observe(a, 'mousedown', OpenLayers.Function.bindAsEventListener(zoomIn, this) );
        m.appendChild(a);
        this.element.appendChild(m);

        var sliderBg = document.createElement('img');
        sliderBg.src = "";
        sliderBg.className = 'png24';
        sliderBg.width = 51;
        sliderBg.height = 201;
        sliderBg.style.position = 'absolute';
        sliderBg.style.left = '0px';
        sliderBg.style.top = '0px';
        sliderBg.useMap = '#Navigator_ImageMap';
        this.element.appendChild(sliderBg);
        
        var handleDiv = document.createElement('div');
        handleDiv.style.position = 'absolute';
        handleDiv.style.top = '6px';
        handleDiv.style.left = '6px';
        handleDiv.style.width = '39px';
        handleDiv.style.height = '16px';
        this.element.appendChild(handleDiv);

        var sliderDiv = document.createElement('div');
        sliderDiv.style.position = 'absolute';
        sliderDiv.style.top = '44px';
        sliderDiv.style.left = '0px';
        sliderDiv.style.width = '51px';
        sliderDiv.style.height = '85px';
        this.element.appendChild(sliderDiv);
        this.divSlider = sliderDiv;

        var sliderHandle = document.createElement('img');
        sliderHandle.src = "";
        sliderHandle.className = 'png24';
        sliderHandle.width = 29;
        sliderHandle.height = 12;
        sliderHandle.style.position = 'absolute';
        sliderHandle.style.left = '11px';
        sliderHandle.style.top = '49px';
        sliderDiv.appendChild(sliderHandle);
        this.slider = sliderHandle;
        this.sliderEvents = new OpenLayers.Events(this, this.slider, null, true,{includeXY: true});
		this.sliderEvents.on({
			"mousedown": this.sliderMouseDown,
			"mousemove": this.sliderMouseDrag,
			"mouseup": this.sliderMouseUp,
			"dblclick": this.stopEvent,
			"click": this.stopEvent
		});
        
        this.activityIndicator = document.createElement('img');
        this.activityIndicator.src = "";
        this.activityIndicator.width = 27;
        this.activityIndicator.height = 6;
        this.activityIndicator.style.position = 'absolute';
        this.activityIndicator.style.top = '3px';
		this.activityIndicator.style.marginLeft = '6px';
        //this.activityIndicator.style.right = '4px';
        handleDiv.appendChild(this.activityIndicator);
        this.activityIndicator.style.visibility = 'hidden';

        this.div.style.position = 'absolute';
        this.div.style.width = '51px';
        this.div.style.height = '204px';
        this.div.style.cursor = 'pointer';
        
        if(this.position.left){
        	this.div.style.left = this.position.left+'px';
        }
        
        if(this.position.right){
        	this.div.style.right = this.position.right+'px';
        }
        
        if(this.position.top){
        	this.div.style.top = this.position.top+'px';
        }
        
        if(this.position.bottom){
        	this.div.style.bottom = this.position.bottom+'px';
        }
        
        
        this.createMapBusyEvent();
        
        return this.div;
    },
    
    pan: function(x,y,e) {
    	this.map.pan(x, y);
        OpenLayers.Event.stop(e);
        return false;
    },
    
    zoomIn: function(e) {
    	this.map.zoomIn();
        OpenLayers.Event.stop(e);
        return false;
    },
    
    zoomOut: function(e) {
    	this.map.zoomOut();
        OpenLayers.Event.stop(e);
        return false;
    },
    
    stopEvent: function(evt) {
        OpenLayers.Event.stop(evt);
        return false;    	
    },
	
	updateSliderPosition: function() {
		var tamanho = parseInt(this.divSlider.style.height)-10;
        var newTop = tamanho-((tamanho/(this.map.getNumZoomLevels()-1))*this.map.getZoom());
        this.slider.style.top = newTop + "px";
        
        var scale = this.map.getScale();
        this.slider.alt = '1:'+Math.round(scale);
        this.slider.title = '1:'+Math.round(scale);
    },
    
    passEventToSlider: function(evt) {
        this.sliderEvents.handleBrowserEvent(evt);
    },
    
    sliderMouseDown: function(evt) {
    	if (!OpenLayers.Event.isLeftClick(evt)) {
            return;
        }
        this.map.events.on({
            "mousemove": this.passEventToSlider,
            "mouseup": this.passEventToSlider,
            scope: this
        });
        this.mouseDragStart = evt.xy.clone();
        this.zoomStart = evt.xy.clone();
        this.div.style.cursor = "move";
        // reset the div offsets just in case the div moved
        this.divSlider.offsets = null; 
        OpenLayers.Event.stop(evt);
    },
    
    sliderMouseDrag: function(evt) {
        if (this.mouseDragStart != null) {
            var deltaY = this.mouseDragStart.y - evt.xy.y;
            var offsets = OpenLayers.Util.pagePosition(this.divSlider);
            if ((evt.clientY - offsets[1]) > 2 && 
                (evt.clientY - offsets[1]) < parseInt(this.divSlider.style.height) - 2) {
                var newTop = parseInt(this.slider.style.top) - deltaY;
                this.slider.style.top = newTop+"px";
                this.mouseDragStart = evt.xy.clone();
            };
            OpenLayers.Event.stop(evt);
        };
    },
    
    sliderMouseUp: function(evt) {
        if (!OpenLayers.Event.isLeftClick(evt)) {
            return;
        }
        if (this.mouseDragStart) {
            this.div.style.cursor="";
            this.map.events.un({
                "mouseup": this.passEventToSlider,
                "mousemove": this.passEventToSlider,
                scope: this
            });
            var deltaY = this.zoomStart.y - evt.xy.y;
            var zoomLevel = this.map.zoom;
            
            if (!this.forceFixedZoomLevel && this.map.fractionalZoom) {
                zoomLevel += deltaY/this.zoomStopHeight;
                zoomLevel = Math.min(Math.max(zoomLevel, 0), 
                                     this.map.getNumZoomLevels() - 1);
            } else {
                zoomLevel += Math.round(deltaY/this.zoomStopHeight);
            };
            
            if(zoomLevel > this.map.getNumZoomLevels() - 1){
            	zoomLevel = this.map.getNumZoomLevels() - 1;
            }else if(zoomLevel < 0){
            	zoomLevel = 0;
            };
            
            this.map.zoomTo(zoomLevel);
            this.mouseDragStart = null;
            this.zoomStart = null;
            this.updateSliderPosition();
            OpenLayers.Event.stop(evt);
        }
    },
    
    createMapBusyEvent : function(){
    	var me = this;
    	
		me.layersLoading = 0;
		var addSliderLayerLoading = function(){
			me.layersLoading++;
			me.setLoading(true);
		};
		
		var removeSliderLayerLoading = function(){
			me.layersLoading--;
			if(me.layersLoading <= 0){
				me.layersLoading = 0;
				me.setLoading(false);
			};
		};
		
		var addSliderLayerBusyEvent = function(layer){
			layer.events.register("loadstart", me, function(){
				addSliderLayerLoading();
			});
			
			layer.events.register("loadend", me, function(){
				removeSliderLayerLoading();
			});
			
			layer.events.register("removed", me, function(){
				layer.events.unregister("loadstart", me, function(){
					addSliderLayerLoading();
				});
				
				layer.events.unregister("loadend", me, function(){
					removeSliderLayerLoading();
				});
			});
		};
		
		me.map.events.register('addlayer', me, function(event){
			addSliderLayerBusyEvent(event.layer);
        });

		for(var i = 0; i < me.map.layers.length; i++){
			addSliderLayerBusyEvent(me.map.layers[i]);
    	};
    },
    
    setLoading: function(loading){
    	var me = this;
    	me.activityIndicator.style.visibility = loading ? '' : 'hidden';
    },
    
    CLASS_NAME: "MapService.Control.Slider"
});